using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public partial class ARPGTestBoarBehaviour : BasePoolElement
{
    Vector3 birthPoint;
    ARPGTestSceneMgr sceneMgr;
    Collider sCollider;
    
    int hp = 3;
    int maxHp = 3;
    public int Hp {
        set {
            hp = value;
            healthBar?.ShowHealth(hp, maxHp);
        }
        get {
            return hp;
        }
    }
    private void Awake()
    {
        sceneMgr = ARPGTestSceneMgr.Instance as ARPGTestSceneMgr;
        nearMonster = new List<ARPGTestBoarBehaviour>();
        sCollider = GetComponentInChildren<Collider>();
        InitAnim();
        InitState();
        InitPatrolPoint();
    }

    public HealthBar healthBar;

    public override void EnPool()
    {
        base.EnPool();
        ObjectPoolManager.Instance.EnPool(healthBar);
    }

    public override void PoolInit()
    {
        base.PoolInit();
        birthPoint = transform.position;
        state.EnterIdleState();

        healthBar = ObjectPoolManager.Instance.DePool<HealthBar>("HealthBar", true, "UINode");
        healthBar.SetParent(transform);
        healthBar.SetSize(new Vector2(100, 20));

        Fllower f = healthBar.GetComponent<Fllower>();
        if (f == null) f = healthBar.gameObject.AddComponent<Fllower>();
        f.Init(transform, Vector3.up * 2);
    }
    public void InitBrith(Vector3 pos) {
        Hp = 3;
        birthPoint = pos;
        transform.rotation = Quaternion.AngleAxis(Random.value * 360, Vector3.up);
        transform.position = birthPoint;
    }
    Animator anim;
    int animAttackHash, animIdolHash, animRunHash, animDeathHash;
    void InitAnim()
    {
        anim = GetComponentInChildren<Animator>();
        animAttackHash = Animator.StringToHash("attack");
        animIdolHash = Animator.StringToHash("idol");
        animRunHash = Animator.StringToHash("run");
        animDeathHash = Animator.StringToHash("death");
    }

    void InitPatrolPoint() {
        patrolPoint = new List<Vector3>();
    }

    float chaseDistanceSqr =4f;
    float backDistance=100f;

    bool CheckPlayerUpdate() {
        return sceneMgr.Player.Stat != ARPGTestPlayerState.Death && Vector3.SqrMagnitude(transform.position - sceneMgr.Player.transform.position) < chaseDistanceSqr ;
    }

    void FixedUpdate()
    {
        state.StateUpdate();
    }

  
    public void Damage(ARPGTestPlayerBehaviour player)
    {
        Hp -= player.attack;
        SoundManager.Instance.Play("pig_01");
        if (Hp < 1)
        {
            player.Meet++;
            state.EnterDeadState();
        }
    }
}

public enum ARPGTestBoarState
{
    Patrol, Combat, Dead, Idle, Chase,Back, Flee, Special
}

public partial class ARPGTestBoarBehaviour : BasePoolElement
{

    ARPGTestBoarStateBehaviour state;
    void InitState()
    {
        state = new ARPGTestBoarStateBehaviour();
        state.onIdleEnter = OnIdleEnter;
        state.onIdleUpdate = OnIdleUpdate;
        state.onPatrolEnter = OnPatrolEnter;
        state.onPatrolUpdate = OnPatrolUpdate;
        state.onChaseEnter = OnChaseEnter;
        state.onChaseExit = OnChaseExit;
        state.onChaseUpdate = OnChaseUpdate;
        state.onCombatEnter = OnCombatEnter;
        state.onCombatUpdate = OnCombatUpdate;
        state.onBackEnter = OnBackEnter;
        state.onBackUpdate = OnBackUpdate;
        state.onDeadEnter = OnDeathEnter;
        state.onDeadUpdate = OnDeathUpdate;


        state.EnterIdleState();
    }

    float IdleTime, IdleCD=3;

    void OnIdleEnter(ARPGTestBoarStateBehaviour s) {
        IdleTime = 0;
        anim.SetTrigger(animIdolHash);
    }

    void OnIdleUpdate(ARPGTestBoarStateBehaviour s) {
        IdleTime += Time.deltaTime;
        if (CheckPlayerUpdate())
        {
            state.EnterChaseState();
        }
        else if (IdleTime>IdleCD)
        {
            while (Random.value < 0.1)
            {
                state.EnterPatrolState();
            }
        }
    }


    List<Vector3> patrolPoint;
    int patroleIndex;
    void OnPatrolEnter(ARPGTestBoarStateBehaviour s) {
        anim.SetTrigger(animRunHash);
        patrolPoint.Clear();
        patroleIndex = 0;
        CreatePatrolPoint();
    }
    void OnPatrolUpdate(ARPGTestBoarStateBehaviour s)
    {
        if (CheckPlayerUpdate())
        {
            state.EnterChaseState();
        }
        else
        {
            Move();
            if (Vector3.Distance(transform.position, patrolPoint[patroleIndex]) < .1f)
            {
                patroleIndex++;
                if (patroleIndex == patrolPoint.Count)
                {
                    state.EnterIdleState();
                }
            }
        }
    }

    int agentid;
    void OnChaseEnter(ARPGTestBoarStateBehaviour s)
    {
        anim.SetTrigger(animRunHash);
        agentid = sceneMgr.AddAgent(transform);
    }

    float playerDissqr, birthDissqr;
    void OnChaseUpdate(ARPGTestBoarStateBehaviour s) {
        //Chase();
        if (PlayerDeadCheck())
        {
            state.EnterBackState();
            return;
        }
       
        transform.position = sceneMgr.GetAgentPos(agentid);

        t = sceneMgr.Player.transform.position - transform.position;
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(t), 0.1f);

        playerDissqr = Vector3.SqrMagnitude(transform.position -sceneMgr.Player.transform.position);
        birthDissqr = Vector3.SqrMagnitude(transform.position - birthPoint);

        if (playerDissqr > 25 || birthDissqr > 175)
        {
            state.EnterBackState();
        }
        if (playerDissqr < 2.25f)
        {
            state.EnterCombatState();
        }
        
    }

    void OnChaseExit(ARPGTestBoarStateBehaviour s) {
        sceneMgr.RemoveAgent(agentid);
    }

    float combatTime, combatCD = 1.5f, combatPointCD = 0.7f;
    bool isChecked;
    void OnCombatEnter(ARPGTestBoarStateBehaviour s) {
        anim.SetTrigger(animAttackHash);
        SoundManager.Instance.Play("pig_01");

        combatTime = 0;
        isChecked = false;
    }

    void OnCombatUpdate(ARPGTestBoarStateBehaviour s) {
        t = sceneMgr.Player.transform.position - transform.position;
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(t), 0.1f);
        combatTime += Time.deltaTime;
        if (!isChecked && combatTime > combatPointCD)
        {
            isChecked = true;
            CheckPalyer();
        }
        if (combatTime > combatCD)
        {
            if (!PlayerDeadCheck())
            {
                state.EnterChaseState();
            }
            else
            {
                state.EnterBackState();
            }
        }
    }

    bool PlayerDeadCheck() {
        return sceneMgr.Player.Stat == ARPGTestPlayerState.Death;
    }

    void CheckPalyer() {
        t = sceneMgr.Player.transform.position - transform.position;
        if (t.sqrMagnitude<3f)
        {
            sceneMgr.Player.Damager(1);
        }
    }

    void OnBackEnter(ARPGTestBoarStateBehaviour s) {
        anim.SetTrigger(animRunHash);
    }

    void OnBackUpdate(ARPGTestBoarStateBehaviour s) {
        Back();
        birthDissqr = Vector3.SqrMagnitude(transform.position - birthPoint);
        if (birthDissqr<0.1)
        {
            state.EnterIdleState();
        }
    }

    void OnDeathEnter(ARPGTestBoarStateBehaviour s)
    {
        sCollider.enabled = false;
        anim.SetTrigger(animDeathHash);
        SoundManager.Instance.Play("pig_02");
        deathTime = 0;
        healthBar?.gameObject.SetActive(false);
    }

    float deathTime, deathCD = 8;
    void OnDeathUpdate(ARPGTestBoarStateBehaviour s) {
        deathTime += Time.deltaTime;
        transform.position -= Vector3.up * 0.1f * Time.deltaTime;
        if (deathTime > deathCD)
        {
            ReBrith();
        }
    }

    void ReBrith() {
        InitBrith(birthPoint);
        state.EnterIdleState();
        sCollider.enabled = true;
        healthBar?.gameObject.SetActive(true);
    }

    void CreatePatrolPoint() {
        Vector3 p;
        for (int i = 0; i < 3; i++)
        {
            p = Random.insideUnitSphere * 3;
            p.y = 0;
            patrolPoint.Add(birthPoint+p);
        }
    }
    float moveSpeed =1;
    private void Move()
    {
        transform.position += transform.forward * moveSpeed * Time.deltaTime; ;
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(patrolPoint[patroleIndex] - transform.position), 0.1f);
    }

    List<ARPGTestBoarBehaviour> nearMonster;
    Vector3 m = Vector3.zero;
    Vector3 c = Vector3.zero;
    Vector3 t = Vector3.zero;
    void Chase() {

        Vector3 moveDir = sceneMgr.Player.transform.position - transform.position;
        moveDir = moveDir.normalized;

        if (Physics.CheckSphere(transform.position,1.5f,1<<31))
        {
            GetMonsters(1.5f, 360);
            m = Vector3.zero;
            c = Vector3.zero;
            t = Vector3.zero;

            for (int i = 0; i < nearMonster.Count; i++)
            {
                if (nearMonster[i] == this) continue;
                //c += nearMonster[i].transform.position;
                m += transform.position - nearMonster[i].transform.position  ;
            }
            c = c - transform.position;
            c = c / (nearMonster.Count - 1);
            c = c.normalized;
            m = m.normalized;
            t = sceneMgr.Player.transform.position - transform.position;
            t = t.normalized;
            transform.position += (m+c+t) * moveSpeed * 1.5f * Time.deltaTime;
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(t), 0.1f);
        }
        else
        {
            transform.position += transform.forward * moveSpeed * 1.5f * Time.deltaTime;
            transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(sceneMgr.Player.transform.position - transform.position), 0.1f);
        }

    }

    void GetMonsters(float range, float angle)
    {
        nearMonster.Clear();
        int c = Physics.OverlapSphereNonAlloc(transform.position, range, sceneMgr.checkMonsters, 1 << 31);
        if (c > 0)
        {
            Vector3 mo;
            for (int i = 0; i < c; i++)
            {
                mo = sceneMgr.checkMonsters[i].transform.position - transform.position;
                if (Vector3.Angle(transform.forward, mo) < angle)
                {
                    nearMonster.Add(sceneMgr.checkMonsters[i].GetComponent<ARPGTestBoarBehaviour>());
                }
            }
        }
    }

    void Back() {
        transform.position += transform.forward * moveSpeed * 3f * Time.deltaTime; ;
        transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.LookRotation(birthPoint - transform.position), 0.1f);
    }


}